package com.pokermind.dse.tcp.handler;

import com.pokermind.dse.tcp.protocol.ProtocolMessage;
import com.pokermind.dse.tcp.router.MessageRouter;
import com.pokermind.common.util.PlainLog;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * Business Handler 业务处理器，负责处理具体的协议消息
 *
 * 功能： 1. 接收解码后的协议消息 2. 路由消息到对应的业务处理器 3. 处理业务异常和错误响应 4. 记录业务处理指标 5. 记录完整的请求体用于调试（通过PlainLog）
 *
 * @author PokerMind Team
 */
@Component
@Sharable
public class BusinessHandler extends SimpleChannelInboundHandler<ProtocolMessage> {

    private static final Logger logger = LoggerFactory.getLogger(BusinessHandler.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private MessageRouter messageRouter;

    @Autowired
    private MeterRegistry meterRegistry;

    // 监控指标
    private Counter messagesReceived;
    private Counter messagesProcessed;
    private Counter messagesErrors;
    private Timer processingTime;

    @PostConstruct
    public void initialize() {
        setupMetrics();
        logger.info("BusinessHandler initialized");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ProtocolMessage msg) throws Exception {
        messagesReceived.increment();

        // V4.7: 移除单独的receive_request日志，请求内容已整合到业务日志中
        // logRequest(msg);

        if (logger.isDebugEnabled()) {
            logger.debug("Received message: {}", msg);
        }

        try {
            // 标记处理开始时间
            msg.markProcessStart();

            // 异步处理消息以避免阻塞I/O线程
            Timer.Sample sample = Timer.start(meterRegistry);

            CompletableFuture<ProtocolMessage> future = messageRouter.routeMessage(msg);

            future.whenComplete((response, throwable) -> {
                try {
                    msg.markProcessEnd();
                    sample.stop(processingTime);

                    if (throwable != null) {
                        handleProcessingError(ctx, msg, throwable);
                    } else if (response != null) {
                        handleProcessingSuccess(ctx, msg, response);
                    } else {
                        logger.warn("No response generated for message: {}", msg);
                    }
                } catch (Exception e) {
                    logger.error("Error in message processing completion: {}", e.getMessage(), e);
                    handleProcessingError(ctx, msg, e);
                }
            });

        } catch (Exception e) {
            logger.error("Error processing message: {}", e.getMessage(), e);
            handleProcessingError(ctx, msg, e);
        }
    }

    /**
     * ✅ 新增：使用PlainLog记录完整的请求信息
     * 完整请求体保存在 reqContent 字段中
     */
    private void logRequest(ProtocolMessage msg) {
        try {
            String rqid = extractRequestId(msg);
            String protocolName = msg.getProtocolName();
            String jsonBody = msg.getJsonBody();
            
            // 美化JSON输出
            String prettyJson = prettyPrintJson(jsonBody);
            
            PlainLog log = new PlainLog()
                .put("op", "receive_request")
                .put("rqid", rqid)
                .put("protocol", protocolName)
                .put("from", msg.getClientId())
                .put("reqContent", prettyJson);  // 完整请求体记录在reqContent字段
            
            logger.info(log.toString());
        } catch (Exception e) {
            logger.warn("Failed to log request: {}", e.getMessage());
        }
    }

    /**
     * ✅ 新增：美化JSON输出
     * 将JSON字符串格式化为可读的格式
     */
    private String prettyPrintJson(String jsonBody) {
        try {
            Object json = objectMapper.readValue(jsonBody, Object.class);
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
        } catch (Exception e) {
            // 如果格式化失败，返回原文本
            return jsonBody;
        }
    }

    /**
     * 处理成功的业务处理结果
     */
    private void handleProcessingSuccess(ChannelHandlerContext ctx, ProtocolMessage request, ProtocolMessage response) {
        try {
            if (ctx.channel().isActive()) {

                // 使用 writeAndFlush 并添加监听器确认发送结果
                ctx.writeAndFlush(response).addListener(future -> {
                    if (future.isSuccess()) {
                        messagesProcessed.increment();
                        if (logger.isDebugEnabled()) {
                            logger.debug("Response sent successfully: reqId={}, protocol={}, duration={}ms",
                                extractRequestId(response), response.getProtocolName(), request.getProcessDurationMillis());
                        }
                    } else {
                        messagesErrors.increment();
                        logger.error("Failed to send response: reqId={}, protocol={}, error={}",
                            extractRequestId(response), response.getProtocolName(),
                            future.cause() != null ? future.cause().getMessage() : "Unknown error");
                    }
                });

            } else {
                logger.warn("Channel inactive, cannot send response: reqId={}, client={}", extractRequestId(response),
                    request.getClientId());
                messagesErrors.increment();
            }
        } catch (Exception e) {
            logger.error("Error in response handling: reqId={}, error={}", extractRequestId(response), e.getMessage(),
                e);
            messagesErrors.increment();
        }
    }

    /**
     * 从响应消息中提取请求ID用于日志追踪
     */
    private String extractRequestId(ProtocolMessage response) {
        try {
            if (response.getJsonNode() != null && response.getJsonNode().has("rqid")) {
                return response.getJsonNode().get("rqid").asText();
            } else if (response.getJsonBody() != null && response.getJsonBody().contains("rqid")) {
                // 简单的字符串匹配提取rqid
                int start = response.getJsonBody().indexOf("\"rqid\":\"") + 8;
                int end = response.getJsonBody().indexOf("\"", start);
                if (start > 7 && end > start) {
                    return response.getJsonBody().substring(start, end);
                }
            }
        } catch (Exception e) {
            // 忽略提取错误
        }
        return "unknown";
    }

    /**
     * 处理业务处理错误
     */
    private void handleProcessingError(ChannelHandlerContext ctx, ProtocolMessage request, Throwable error) {
        messagesErrors.increment();

        logger.error("Business processing error for {}: {} - {}", request.getProtocolName(),
            error.getClass().getSimpleName(), error.getMessage());

        try {
            // 创建错误响应
            ProtocolMessage errorResponse;
            if (error instanceof IllegalArgumentException) {
                // 参数错误
                errorResponse =
                    ProtocolMessage.createBusinessErrorResponse(request, "Invalid parameters", error.getMessage());
            } else if (error instanceof RuntimeException) {
                // 业务逻辑错误
                errorResponse =
                    ProtocolMessage.createBusinessErrorResponse(request, "Business error", error.getMessage());
            } else {
                // 系统错误
                errorResponse = ProtocolMessage.createErrorResponse(request, 500, "Internal server error");
            }

            if (ctx.channel().isActive()) {
                ctx.writeAndFlush(errorResponse);
            }

        } catch (Exception e) {
            logger.error("Error creating error response: {}", e.getMessage(), e);
            // 最后手段：关闭连接
            ctx.close();
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
        super.channelReadComplete(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("Business handler error for {}: {}", ctx.channel().remoteAddress(), cause.getMessage(), cause);
        messagesErrors.increment();
        ctx.close();
    }

    /**
     * 设置监控指标
     */
    private void setupMetrics() {
        messagesReceived =
            Counter.builder("tcp.messages.received").description("Number of messages received").register(meterRegistry);

        messagesProcessed =
            Counter.builder("tcp.messages.processed").description("Number of messages processed successfully")
                .register(meterRegistry);

        messagesErrors = Counter.builder("tcp.messages.errors").description("Number of message processing errors")
            .register(meterRegistry);

        processingTime = Timer.builder("tcp.messages.processing.time").description("Message processing time")
            .register(meterRegistry);
    }

    /**
     * 获取业务处理统计信息
     */
    public BusinessStats getBusinessStats() {
        return new BusinessStats((long)messagesReceived.count(), (long)messagesProcessed.count(),
            (long)messagesErrors.count(), processingTime.mean(TimeUnit.MILLISECONDS),
            processingTime.max(TimeUnit.MILLISECONDS));
    }

    /**
     * 业务统计信息
     */
    public static class BusinessStats {
        private final long messagesReceived;
        private final long messagesProcessed;
        private final long messagesErrors;
        private final double averageProcessingTime;
        private final double maxProcessingTime;

        public BusinessStats(long messagesReceived, long messagesProcessed, long messagesErrors,
            double averageProcessingTime, double maxProcessingTime) {
            this.messagesReceived = messagesReceived;
            this.messagesProcessed = messagesProcessed;
            this.messagesErrors = messagesErrors;
            this.averageProcessingTime = averageProcessingTime;
            this.maxProcessingTime = maxProcessingTime;
        }

        // Getters
        public long getMessagesReceived() {
            return messagesReceived;
        }

        public long getMessagesProcessed() {
            return messagesProcessed;
        }

        public long getMessagesErrors() {
            return messagesErrors;
        }

        public double getAverageProcessingTime() {
            return averageProcessingTime;
        }

        public double getMaxProcessingTime() {
            return maxProcessingTime;
        }

        @Override
        public String toString() {
            return String.format("BusinessStats{received=%d, processed=%d, errors=%d, avgTime=%.2fms, maxTime=%.2fms}",
                messagesReceived, messagesProcessed, messagesErrors, averageProcessingTime, maxProcessingTime);
        }
    }
}
